/**
 * Copyright (c) 2008 - TheNittyGritty - Thomas Brekelmans
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package nl.thenittygritty.command 
{

	/**
	 * CommandHistory keeps track of each executed ICommand passed along to its 
	 * addCommand method.
	 * Use command history in each ICommandReceiver implementation with concrete 
	 * commands that implement IUndoableCommand and IRedoableCommand to 
	 * respectively create an undoable and/or redoable application. 
	 * You should invoke addCommand in your Event.COMPLETE listener for 
	 * each command.
	 */
	public class CommandHistory 
	{
		private var commands:Array;
		private var historyIndex:uint;
		
		/**
		 * Creates a new CommandHistory.
		 * If you want to keep track of every executed command in your 
		 * application, make sure you only use one instance of this class.
		 * If you need to keep track of multiple command history's within your 
		 * application, create and maintain multiple instances of this class.
		 */
		public function CommandHistory() 
		{
			commands = new Array();
			historyIndex = 0;
		}
		
		/**
		 * Adds an implementation of ICommand to it's internal store of executed 
		 * commands at the current position of the history index. 
		 * All commands after the newly added command will be removed.
		 */
		public function addCommand(command:ICommand):void
		{
			commands[historyIndex++] = command;
			commands.splice(historyIndex, commands.length - historyIndex);
		}
		
		/**
		 * Returns the command before the current command and decrements 
		 * the historyIndex.
		 * If no previous command is available, null is returned and 
		 * the historyIndex is set to -1.
		 */
		public function getPreviousCommand():ICommand
		{
			if (hasPreviousCommand() == true)
			{
				return commands[historyIndex--];	
			}
			else
			{
				historyIndex = -1;
				return null;	
			}
		}
		
		/**
		 * Returns the command after the current command and increments 
		 * the historyIndex.
		 * If no next command is available, null is returned and 
		 * the historyIndex is set to the total number of commands in history.
		 */
		public function getNextCommand():ICommand
		{
			if (hasNextCommand() == true)
			{
				return commands[historyIndex++];	
			}
			else
			{
				historyIndex = commands.length;
				return null;	
			}
		}

		/**
		 * Returns whether or not any commands exist before the current 
		 * history index.
		 */
		public function hasPreviousCommand():Boolean
		{
			return historyIndex > 0;
		}
		
		/**
		 * Returns whether or not any commands exist after the current 
		 * history index.
		 */
		public function hasNextCommand():Boolean
		{
			return historyIndex < commands.length;
		}
		
		/**
		 * Returns the current history index (i.e. the index of the cursor 
		 * which determines which command was accessed last from this 
		 * command history).
		 */
		public function getHistoryIndex():uint
		{
			return historyIndex;
		}
		
		/**
		 * Returns the name of the class in a String.
		 */
		public function toString():String 
		{
			return "CommandHistory";
		}
	}
}
